package source;

import source.Entity.*;
import source.view.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

/**
 * Controller class is the input interface for the application.
 * The logic occurs in keyPressed(), which gets triggered when
 * input is given to the system.  A Driver attribute is necessary so
 * Controller can send messages back to the application.
 *  */

public class Controller implements MouseListener, KeyListener {
	
	protected Driver driver;
	private EntityType lastSelected;
	private boolean userCreatingMission;
	private int destTileX;
	private int destTileY;
	
	public Controller(Driver d) {
		driver = d;
		lastSelected = EntityType.UNIT;
		userCreatingMission = false;
		destTileX = 0;
		destTileY = 0;
	}	
	
	public void mouseClicked(MouseEvent arg0) {

	}

	public void mouseEntered(MouseEvent arg0) {

	}

	public void mouseExited(MouseEvent arg0) {

	}

	public void mousePressed(MouseEvent arg0) {

	}

	public void mouseReleased(MouseEvent arg0) {

	}

	/**  keyPressed method gets called when a key on the keyboard gets pressed.
	 *  A switch/case statement handles the decyphering of which key got pressed,
	 *  and what to do with it.
	 *  
	 *  Key Binding Chart
	 *  
	 *  1 		- SW
	 *  2 		- S
	 *  3 		- SE
	 *  4 		- W
	 *  6 		- E
	 *  7 		- NW
	 *  8 		- N
	 *  9 		- NE
	 *  [SPACE] - Current unit does nothing this turn
	 *  [TAB]	- Select next unit
	 *  S		- Select next structure
	 *  [ENTER] - End Turn
	 *  U		- Set View to Unit Overview
	 *  T		- Set View to Structure Overview
	 *  A		- Set View to Main view
	 *  Q		- Start/End Mission selection
	 *  H		- Heal Unit
	 *  C		- Build Colonist
	 *  R		- Build Ranged
	 *  E		- Build Explorer
	 *  M		- Build Melee
	 *  B		- Build Base
	 *  
	 *  
	 */
	public void keyPressed(KeyEvent e) {

		if(userCreatingMission)
		{
			creatingMission(e);
		}
		else
		{
			genericKeyPressed(e);
		}
		
		
			if(lastSelected == EntityType.STRUCTURE)
			{
				Tile currentSelection = driver.getCurrentPlayer().getCurrentStructure().getPosition();
				driver.getMainScreen().getAreaViewport().setSelected(currentSelection.getX(), currentSelection.getY());
			}
			else
			{
				if(userCreatingMission)
				{
					driver.getMainScreen().getAreaViewport().setSelected(destTileX, destTileY);
				}
				else
				{
					Tile currentSelection = driver.getCurrentPlayer().getCurrentUnit().getPosition();
					driver.getMainScreen().getAreaViewport().setSelected(currentSelection.getX(), currentSelection.getY());
				}
			}
			
			driver.getMainScreen().getStatusViewport().update();
				AreaViewport a;
				a = driver.getMainScreen().getAreaViewport();
				a.update();
				driver.getMainScreen().focusMap(a.getSelectedX(), a.getSelectedY());
	}

	public void keyReleased(KeyEvent e) {
	}

	public void keyTyped(KeyEvent e) {
	}
	
	public void genericKeyPressed(KeyEvent e)
	{
		switch(e.getKeyCode())
		{
			
		case KeyEvent.VK_S:
			if(driver.getCurrentPlayer().getBasesArray().length > 0)
			{
				MainScreen.writeToConsole("Controller: Select Next Structure", Color.BLUE);
				driver.getCurrentPlayer().selectNextStructure();
				driver.getMainScreen().getStatusViewport().displayStructure();
				lastSelected = EntityType.STRUCTURE;
			}
			else
				MainScreen.writeToConsole("Controller:  Cannot select next structure.  No structures found.", Color.BLUE);
			break;
			
		case KeyEvent.VK_TAB:
			if(driver.getCurrentPlayer().getUnitsArray().length > 0)
			{
				MainScreen.writeToConsole("Controller: Select Next Unit", Color.BLUE);
				driver.getCurrentPlayer().selectNextUnit();
				driver.getMainScreen().getStatusViewport().displayUnit();
				lastSelected = EntityType.UNIT;
			}
			else
				MainScreen.writeToConsole("Controller:  Cannot select next unit.  No units found.", Color.BLUE);
			break;
			
		case KeyEvent.VK_ENTER:
			MainScreen.writeToConsole("Controller: Player " + driver.getCurrentPlayer().getID() + " ending turn", Color.BLUE);
			driver.nextTurn();
			//quick fix,  change so application doesnt crash if one player has no more units
			lastSelected = EntityType.UNIT;
			driver.getMainScreen().getStatusViewport().displayUnit();
			break;
			
		case KeyEvent.VK_U:
			MainScreen.writeToConsole("Controller: Change View to Unit Overview", Color.BLUE);
			driver.getMainScreen().switchToUnitOverview();
			break;
			
		case KeyEvent.VK_T:
			MainScreen.writeToConsole("Controller: Change View to Structure Overview", Color.BLUE);
			driver.getMainScreen().switchToStructureOverview();
			break;
			
		case KeyEvent.VK_A:
			MainScreen.writeToConsole("Controller: Change View to Main View", Color.BLUE);
			driver.getMainScreen().switchToAreaViewport();
			break;
		
		default:
			if(lastSelected == EntityType.UNIT)
				unitKeyPressed(e);
			else
				structureKeyPressed(e);
		}
	}

	private void unitKeyPressed(KeyEvent e)
	{
			if(driver.getCurrentPlayer().getCurrentUnit().getDestinationTile() == null)
			{
				switch(e.getKeyCode())
				{
	
				case KeyEvent.VK_SPACE:
					MainScreen.writeToConsole("Controller: Current Unit does nothing this turn", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setRemainingMoves(0);
					driver.getCurrentPlayer().selectNextUnit();
					driver.getMainScreen().getStatusViewport().displayUnit();
					lastSelected = EntityType.UNIT;
					break;
					
				case KeyEvent.VK_NUMPAD8:
					MainScreen.writeToConsole("Controller: Move unit north", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("N");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),8);
					break;
					
				case KeyEvent.VK_NUMPAD9:
					MainScreen.writeToConsole("Controller: Move unit northeast", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("NE");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),9);
					break;	
					
				case KeyEvent.VK_NUMPAD6:
					MainScreen.writeToConsole("Controller: Move unit east", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("E");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),6);
					break;
					
				case KeyEvent.VK_NUMPAD3:
					MainScreen.writeToConsole("Controller: Move unit southeast", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("SE");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),3);
					break;
					
				case KeyEvent.VK_NUMPAD2:
					MainScreen.writeToConsole("Controller: Move unit south", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("S");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),2);
					break;
					
				case KeyEvent.VK_NUMPAD1:
					MainScreen.writeToConsole("Controller: Move unit southwest", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("SW");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),1);
					break;	
					
				case KeyEvent.VK_NUMPAD4:
					MainScreen.writeToConsole("Controller: Move unit west", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("W");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),4);
					break;
					
				case KeyEvent.VK_NUMPAD7:
					MainScreen.writeToConsole("Controller: Move unit northwest", Color.BLUE);
					driver.getCurrentPlayer().getCurrentUnit().setOrientation("NW");
					driver.getMap().move(driver.getCurrentPlayer().getCurrentUnit(),7);
					break;
					
				case KeyEvent.VK_B:
					MainScreen.writeToConsole("Controller: Create Base", Color.BLUE);
					Unit temp = driver.getCurrentPlayer().getCurrentUnit();
					if(temp instanceof Colonist)
					{
						((Colonist)temp).createBase();
					}			
					else
						MainScreen.writeToConsole("Controller: Unit cannot create Base", Color.BLUE);
					break;
					
				case KeyEvent.VK_Q:
					MainScreen.writeToConsole("Controller: Start creating Mission", Color.BLUE);
					userCreatingMission = true;
					destTileX = driver.getCurrentPlayer().getCurrentUnit().getPosition().getX();
					destTileY = driver.getCurrentPlayer().getCurrentUnit().getPosition().getY();
					MainScreen.writeToConsole("Controller:  destX: " + destTileX + " destY: " + destTileY, Color.BLUE);
					break;
					
				case KeyEvent.VK_H:
					MainScreen.writeToConsole("Controller: Heal Unit", Color.BLUE);
					Unit hurtUnit = driver.getCurrentPlayer().getCurrentUnit();
					if (hurtUnit != null) {
						Base tileBase = hurtUnit.getPosition().getBase();
						if (tileBase != null)
						{
							tileBase.healUnit(hurtUnit);
						}
					}
					break;
			}
			}
	}
	
	private void structureKeyPressed(KeyEvent e)
	{
		
		switch(e.getKeyCode())
		{
			case KeyEvent.VK_C:
				MainScreen.writeToConsole("Controller: Create Colonist", Color.BLUE);
				createUnit(UnitType.COLONIST);
				break;
				
			case KeyEvent.VK_E:
				MainScreen.writeToConsole("Controller: Create Explorer", Color.BLUE);
				createUnit(UnitType.EXPLORER);
				break;
				
			case KeyEvent.VK_M:
				MainScreen.writeToConsole("Controller: Create Melee", Color.BLUE);
				createUnit(UnitType.MELEE);
				break;
				
			case KeyEvent.VK_R:
				MainScreen.writeToConsole("Controller: Create Ranged", Color.BLUE);
				createUnit(UnitType.RANGED);
				break;
		}
	}
		
	private void createUnit(UnitType u)
	{
			if(lastSelected == EntityType.STRUCTURE)
			{
				if(driver.getCurrentPlayer().getOre() >= u.ore())
				{
				driver.getCurrentPlayer().modifyOre(-u.ore());
				Base currentBase = driver.getCurrentPlayer().getCurrentStructure();
				currentBase.beginBuilding(u);
				}
			}
	}
	
	private void creatingMission(KeyEvent e)
	{
		boolean destTileMoved = false;
		switch(e.getKeyCode())
		{
			case KeyEvent.VK_Q:
				MainScreen.writeToConsole("Controller:  Finish creating mission", Color.BLUE);
				userCreatingMission = false;
				Tile destTile = driver.getMap().getSquare(destTileX, destTileY);
				if(driver.getCurrentPlayer().addMission(destTile))
				{
					MainScreen.writeToConsole("Controller: Unit got its mission tile");
				}
				driver.getCurrentPlayer().selectNextUnit();
				driver.getMainScreen().getStatusViewport().displayUnit();
				lastSelected = EntityType.UNIT;
				MainScreen.writeToConsole("Controller:  Units destination tile  is at X: " +
							destTile.getX() + " Y: " + destTile.getY(), Color.BLUE);
				return;
				
			case KeyEvent.VK_NUMPAD8:
				MainScreen.writeToConsole("Controller: Move mission tile north", Color.BLUE);
				if(destTileY > 0)
				{
					destTileY -= 1;
					destTileMoved = true;
				}
				break;
				
			case KeyEvent.VK_NUMPAD9:
				MainScreen.writeToConsole("Controller: Move mission tile northeast", Color.BLUE);
				if(destTileX < driver.getMap().getDimension().width - 1 && destTileY > 0)
				{
					destTileX += 1;
					destTileY -= 1;
					destTileMoved = true;
				}
				break;	
				
			case KeyEvent.VK_NUMPAD6:
				MainScreen.writeToConsole("Controller: Move mission tile east", Color.BLUE);
				if(destTileX < driver.getMap().getDimension().width - 1)
				{
					destTileX += 1;
					destTileMoved = true;
				}
				break;
				
			case KeyEvent.VK_NUMPAD3:
				MainScreen.writeToConsole("Controller: Move mission tile southeast", Color.BLUE);
				if(destTileX < driver.getMap().getDimension().width  -1 && destTileY < driver.getMap().getDimension().height - 1) {
					destTileX += 1;
					destTileY += 1;
					destTileMoved = true;
				}
				break;
				
			case KeyEvent.VK_NUMPAD2:
				MainScreen.writeToConsole("Controller: Move mission tile south", Color.BLUE);
				if(destTileY < driver.getMap().getDimension().height - 1)
				{
					destTileY += 1;
					destTileMoved = true;
				}
				break;
				
			case KeyEvent.VK_NUMPAD1:
				MainScreen.writeToConsole("Controller: Move mission tile southwest", Color.BLUE);
				if(destTileX > 0 && destTileY < driver.getMap().getDimension().height - 1)
				{
					destTileX -= 1;
					destTileY += 1;
					destTileMoved = true;
				}
				break;	
				
			case KeyEvent.VK_NUMPAD4:
				MainScreen.writeToConsole("Controller: Move mission tile west", Color.BLUE);
				if(destTileX > 0)
				{
					destTileX -= 1;
					destTileMoved = true;
				}
				break;
				
			case KeyEvent.VK_NUMPAD7:
				MainScreen.writeToConsole("Controller: Move mission tile northwest", Color.BLUE);
				if(destTileX > 0 && destTileY > 0)
				{
					destTileX -= 1;
					destTileY -= 1;
					destTileMoved = true;
				}
				break;
		}
		
		if(destTileMoved)
		{
			MainScreen.writeToConsole("Controller:  destX: " + destTileX + " destY: " + destTileY, Color.BLUE);
		}
		
		if(userCreatingMission)
		{
			driver.getMainScreen().getAreaViewport().setSelected(destTileX, destTileY);
		}
		else
		{
			Tile currentSelection = driver.getCurrentPlayer().getCurrentUnit().getPosition();
			driver.getMainScreen().getAreaViewport().setSelected(currentSelection.getX(), currentSelection.getY());	
		}
		
	}
}
